#ifndef _WX_GTK_WINDOW_H_
#define _WX_GTK_WINDOW_H_

#include "wx/dynarray.h"

struct wxGtkIMData;

WX_DEFINE_EXPORTED_ARRAY_PTR( GdkWindow *, wxArrayGdkWindows );

class wxWindow;
typedef void ( *wxInsertChildFunction )( wxWindow*, wxWindow* );

class wxWindow : public wxWindowBase {
  public:
    wxWindow();
    wxWindow( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr );
    bool Create( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr );
    virtual ~wxWindow();
    virtual void SetLabel( const wxString & ( label ) ) { }
    virtual wxString GetLabel() const { return wxEmptyString; }
    virtual bool Destroy();
    virtual void Raise();
    virtual void Lower();
    virtual bool Show( bool show = true );
    virtual bool Enable( bool enable = true );
    virtual void SetWindowStyleFlag( long style );
    virtual bool IsRetained() const;
    virtual void SetFocus();
    virtual bool AcceptsFocus() const;
    virtual bool Reparent( wxWindowBase *newParent );
    virtual void WarpPointer( int x, int y );
    virtual void Refresh( bool eraseBackground = true, const wxRect *rect = ( const wxRect * ) NULL );
    virtual void Update();
    virtual void ClearBackground();
    virtual bool SetBackgroundColour( const wxColour &colour );
    virtual bool SetForegroundColour( const wxColour &colour );
    virtual bool SetCursor( const wxCursor &cursor );
    virtual bool SetFont( const wxFont &font );
    virtual bool SetBackgroundStyle( wxBackgroundStyle style ) ;
    virtual int GetCharHeight() const;
    virtual int GetCharWidth() const;
    virtual void GetTextExtent( const wxString& string, int *x, int *y, int *descent = ( int * ) NULL,
                                int *externalLeading = ( int * ) NULL, const wxFont *theFont = ( const wxFont * ) NULL )
    const;
    virtual void SetScrollbar( int orient, int pos, int thumbVisible, int range, bool refresh = true );
    virtual void SetScrollPos( int orient, int pos, bool refresh = true );
    virtual int GetScrollPos( int orient ) const;
    virtual int GetScrollThumb( int orient ) const;
    virtual int GetScrollRange( int orient ) const;
    virtual void ScrollWindow( int dx, int dy, const wxRect* rect = ( wxRect * ) NULL );
    virtual bool ScrollLines( int lines );
    virtual bool ScrollPages( int pages );
    #if wxUSE_DRAG_AND_DROP
    virtual void SetDropTarget( wxDropTarget *dropTarget );
    #endif
    virtual void AddChild( wxWindowBase *child );
    virtual void RemoveChild( wxWindowBase *child );
    virtual void SetLayoutDirection( wxLayoutDirection dir );
    virtual wxLayoutDirection GetLayoutDirection() const;
    virtual wxCoord AdjustForLayoutDirection( wxCoord x, wxCoord width, wxCoord widthTotal ) const;
    virtual bool DoIsExposed( int x, int y ) const;
    virtual bool DoIsExposed( int x, int y, int w, int h ) const;
    void SetDoubleBuffered( bool on );
    virtual bool IsDoubleBuffered() const;
    virtual WXWidget GetHandle() const { return m_widget; }
    virtual void OnInternalIdle();
    void GtkUpdate();
    void OnIdle( wxIdleEvent & ( event ) ) {}
    virtual void OnParentEnable( bool ( enable ) ) {}
    bool PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size );
    void PostCreation();
    void DoAddChild( wxWindow *child );
    void GtkSendPaintEvents();
    virtual GtkWidget* GetConnectWidget();
    void ConnectWidget( GtkWidget *widget );
    int GTKCallbackCommonPrologue( struct _GdkEventAny *event ) const;
    virtual bool GTKProcessEvent( wxEvent& event ) const;
    static wxLayoutDirection GTKGetLayout( GtkWidget *widget );
    static void GTKSetLayout( GtkWidget *widget, wxLayoutDirection dir );
  protected:
    virtual bool GTKWidgetNeedsMnemonic() const;
    virtual void GTKWidgetDoSetMnemonic( GtkWidget* w );
    virtual GdkWindow *GTKGetWindow( wxArrayGdkWindows& windows ) const;
    bool GTKIsOwnWindow( GdkWindow *window ) const;
    bool GTKSetDelayedFocusIfNeeded();
  public:
    PangoContext   *GtkGetPangoDefaultContext();
    #if wxUSE_TOOLTIPS
    virtual void ApplyToolTip( GtkTooltips *tips, const wxChar *tip );
    #endif
    void GtkUpdateSize() { m_sizeSet = false; }
    void GtkShowOnIdle() { m_showOnIdle = true; }
    bool GtkShowFromOnIdle();
    virtual void FixUpMouseEvent( GtkWidget *widget, wxCoord& x, wxCoord& y ) { }
    virtual bool IsTransparentForMouse() const { return false; }
    virtual bool IsRadioButton() const { return false; }
    wxEventType GetScrollEventType( GtkRange* range );
    void BlockScrollEvent();
    void UnblockScrollEvent();
    int m_x, m_y;
    int m_width, m_height;
    int m_oldClientWidth, m_oldClientHeight;
    GtkWidget *m_widget;
    GtkWidget *m_wxwindow;
    GtkWidget *m_focusWidget;
    wxGtkIMData *m_imData;
    enum ScrollDir {
      ScrollDir_Horz,
      ScrollDir_Vert,
      ScrollDir_Max
    };
    GtkRange* m_scrollBar[ScrollDir_Max];
    double m_scrollPos[ScrollDir_Max];
    bool m_blockValueChanged[ScrollDir_Max];
    static ScrollDir ScrollDirFromOrient( int orient ) {
      return orient == wxVERTICAL ? ScrollDir_Vert : ScrollDir_Horz;
    }
    static int OrientFromScrollDir( ScrollDir dir ) {
      return dir == ScrollDir_Horz ? wxHORIZONTAL : wxVERTICAL;
    }
    ScrollDir ScrollDirFromRange( GtkRange *range ) const;
    bool m_needParent: 1;
    bool m_noExpose: 1;
    bool m_nativeSizeEvent: 1;
    bool m_hasScrolling: 1;
    bool m_hasVMT: 1;
    bool m_sizeSet: 1;
    bool m_resizing: 1;
    bool m_acceptsFocus: 1;
    bool m_hasFocus: 1;
    bool m_isScrolling: 1;
    bool m_clipPaintRegion: 1;
    wxRegion m_nativeUpdateRegion;
    bool m_dirtyTabOrder: 1;
    bool m_needsStyleChange: 1;
    bool m_mouseButtonDown: 1;
    bool m_blockScrollEvent: 1;
    bool m_showOnIdle: 1;
    wxInsertChildFunction  m_insertCallback;
  protected:
    virtual void DoClientToScreen( int *x, int *y ) const;
    virtual void DoScreenToClient( int *x, int *y ) const;
    virtual void DoGetPosition( int *x, int *y ) const;
    virtual void DoGetSize( int *width, int *height ) const;
    virtual void DoGetClientSize( int *width, int *height ) const;
    virtual void DoSetSize( int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO );
    virtual void DoSetClientSize( int width, int height );
    virtual void DoMoveWindow( int x, int y, int width, int height );
    #if wxUSE_MENUS_NATIVE
    virtual bool DoPopupMenu( wxMenu *menu, int x, int y );
    #endif
    virtual void DoCaptureMouse();
    virtual void DoReleaseMouse();
    #if wxUSE_TOOLTIPS
    virtual void DoSetToolTip( wxToolTip *tip );
    #endif
    void Init();
    virtual void DoMoveInTabOrder( wxWindow *win, MoveKind move );
    void RealizeTabOrder();
    GtkRcStyle *CreateWidgetStyle( bool forceStyle = false );
    virtual void ApplyWidgetStyle( bool forceStyle = false );
    virtual void DoApplyWidgetStyle( GtkRcStyle *style );
    static void GtkScrolledWindowSetBorder( GtkWidget* w, int style );
    void GTKUpdateCursor();
  private:
    enum ScrollUnit { ScrollUnit_Line, ScrollUnit_Page, ScrollUnit_Max };
    bool DoScrollByUnits( ScrollDir dir, ScrollUnit unit, int units );
    DECLARE_DYNAMIC_CLASS( wxWindow )
    DECLARE_NO_COPY_CLASS( wxWindow )
};

extern wxWindow *wxFindFocusedChild( wxWindow *win );

#endif
